﻿using System;
using UnityEngine;

namespace winS.Unity
{
    /// <summary>
    /// Provides mathematics functions.
    /// this is a high-level wrapper for <see cref="Mathf"/>.
    /// </summary>
    public static class Math
    {
        /// <summary>
        /// 自然常数e
        /// </summary>
        public const float e = 2.718281f;
        /// <summary>
        /// π
        /// </summary>
        public const float pi = 3.141592f;
        /// <summary>
        /// 正周期
        /// </summary>
        public const float pi2 = 2f * pi;
        /// <summary>
        /// 角度转弧度
        /// </summary>
        public const float deg2Rad = pi / 180f;
        /// <summary>
        /// 弧度转角度
        /// </summary>
        public const float rad2deg = 180f / pi;

        /// <summary>
        /// 对数.
        /// 求以 常数e 为底, <paramref name="antilog"/> 的对数
        /// </summary>
        public static float LogE(float antilog)
        {
            return Mathf.Log(antilog);
        }
        /// <summary>
        /// 对数.
        /// 求以 常数10 为底, <paramref name="antilog"/> 的对数
        /// </summary>
        public static float Log10(float antilog)
        {
            return Mathf.Log10(antilog);
        }
        /// <summary>
        /// 对数.
        /// 求以<paramref name="baseNumber"/> 为底, <paramref name="antilog"/> 的对数
        /// </summary>
        public static float Log(float antilog, float baseNumber)
        {
            return Mathf.Log(antilog, baseNumber);
        }

        /// <summary>
        /// 阶乘
        /// </summary>
        public static float Factorial(float naturalNumber)
        {
            float result = 1f;
            while (naturalNumber > 1) result *= naturalNumber--;
            return result;
        }
        /// <summary>
        /// 溢出.
        /// 计算值 <paramref name="value"/> 是否溢出区间 [<paramref name="min"/>, <paramref name="max"/>]; 如果溢出, 溢出了多少间隔 <paramref name="overflowInterval"/>
        /// <para>如果 <paramref name="value"/> 在 [<paramref name="min"/>, <paramref name="max"/>] 内,返回0.</para>
        /// <para>如果 <paramref name="value"/> 小于 <paramref name="min"/>, 返回负比值</para>
        /// <para>如果 <paramref name="value"/> 大于 <paramref name="max"/>, 返回正比值</para>
        /// </summary>
        public static float Overflow(float value, float min, float max, float overflowInterval)
        {
            if (value < min) return (value - min) / overflowInterval;
            if (value > max) return (value - max) / overflowInterval;
            return 0f;
        }

        /// <summary>
        /// 平方
        /// </summary>
        public static float Square(float baseNumber)
        {
            return Pow(baseNumber, 2f);
        }
        /// <summary>
        /// 平方根
        /// </summary>
        public static float Sqrt(float value)
        {
            return Mathf.Sqrt(value);
        }
        /// <summary>
        /// e乘方
        /// </summary>
        public static float Exp(float exponent)
        {
            return Mathf.Exp(exponent);
        }
        /// <summary>
        /// 乘方
        /// </summary>
        public static float Pow(float baseNumber, float exponent)
        {
            return Mathf.Pow(baseNumber, exponent);
        }

        /// <summary>
        /// 插值.
        /// 以比值 <paramref name="t"/> 在区间 [<paramref name="a"/>, <paramref name="b"/>] 中线性取值
        /// </summary>
        public static float Lerp(float a, float b, float t)
        {
            return a + (b - a) * t;
        }
        /// <summary>
        /// 插值.
        /// 以比值 <paramref name="t"/> 在区间 <paramref name="range"/> 中线性取值
        /// </summary>
        public static float Lerp(Vector2 range, float t)
        {
            return Lerp(range.x, range.y, t);
        }
        /// <summary>
        /// 插值.
        /// 以比值 <paramref name="t"/> 在区间 [<paramref name="a"/>, <paramref name="b"/>] 中线性取值.
        /// 总是将 <paramref name="t"/> 约束在区间 [0, 1] 内
        /// </summary>
        public static float Lerp01(float a, float b, float t)
        {
            if (t < 0f) t = 0f;
            else if (t > 1f) t = 1f;
            return a + (b - a) * t;
        }
        /// <summary>
        /// 平滑阶梯.
        /// 以比值 <paramref name="t"/> 在区间 [<paramref name="a"/>, <paramref name="b"/>] 中平滑取值
        /// </summary>
        public static float SmoothStep(float a, float b, float t)
        {
            return a + (b - a) * t * t * (3f - 2f * t);
        }
        /// <summary>
        /// 平滑阶梯.
        /// 以比值 <paramref name="t"/> 在区间 [<paramref name="a"/>, <paramref name="b"/>] 中平滑取值.
        /// 总是将 <paramref name="t"/> 约束在区间 [0, 1] 内
        /// </summary>
        public static float SmoothStep01(float a, float b, float t)
        {
            if (t < 0f) t = 0f;
            else if (t > 1f) t = 1f;
            return a + (b - a) * t * t * (3f - 2f * t);
        }

        /// <summary>
        /// 约束 <paramref name="value"/> 到区间 [<paramref name="minValue"/>, <paramref name="maxValue"/>] 
        /// </summary>
        public static int Clamp(int value, int minValue, int maxValue)
        {
            if (maxValue < minValue) (maxValue, minValue) = (minValue, maxValue);
            if (value < minValue) return minValue;
            else if (value > maxValue) return maxValue;
            return value;
        }
        /// <summary>
        /// 约束 <paramref name="value"/> 到区间 [<paramref name="minValue"/>, <paramref name="maxValue"/>] 
        /// </summary>
        public static bool Clamp(ref int value, int minValue, int maxValue)
        {
            if (maxValue < minValue) (maxValue, minValue) = (minValue, maxValue);
            bool clamped = false;
            if (value < minValue)
            {
                clamped = true;
                value = minValue;
            }
            else if (value > maxValue)
            {
                clamped = true;
                value = maxValue;
            }
            return clamped;
        }
        /// <summary>
        /// 约束 <paramref name="value"/> 到区间 [<paramref name="minValue"/>, <paramref name="maxValue"/>] 
        /// </summary>
        public static float Clamp(float value, float minValue, float maxValue)
        {
            if (maxValue < minValue) (maxValue, minValue) = (minValue, maxValue);
            if (value < minValue) return minValue;
            else if (value > maxValue) return maxValue;
            return value;
        }
        /// <summary>
        /// 约束 <paramref name="value"/> 到区间 [<paramref name="minValue"/>, <paramref name="maxValue"/>] 
        /// </summary>
        public static bool Clamp(ref float value, float minValue, float maxValue)
        {
            if (maxValue < minValue) (maxValue, minValue) = (minValue, maxValue);
            bool clamped = false;
            if (value < minValue)
            {
                clamped = true;
                value = minValue;
            }
            else if (value > maxValue)
            {
                clamped = true;
                value = maxValue;
            }
            return clamped;
        }

        /// <summary>
        /// Clamp <paramref name="value"/> within [0, 1]
        /// </summary>
        public static float Clamp01(float value)
        {
            if (value < 0) return 0f;
            if (value > 1) return 1f;
            return value;
        }
        /// <summary>
        /// Clamp <paramref name="value"/> within [0, 1]
        /// </summary>
        /// <returns>If <paramref name="value"/> is successfully Clamp, return true</returns>
        public static bool Clamp01(ref float value)
        {
            if (value < 0)
            {
                value = 0f;
                return true;
            }
            if (value > 1)
            {
                value = 1f;
                return true;
            }
            return false;
        }

        /// <summary>
        /// 重映射.
        /// 将区间 [<paramref name="minValueBefore"/>, <paramref name="maxValueBefore"/>] 内的值 <paramref name="value"/> 映射到区间 [<paramref name="minValueAfter"/>, <paramref name="maxValueAfter"/>]
        /// </summary>
        /// <param name="value">映射值</param>
        /// <param name="minValueBefore">映射前最小值</param>
        /// <param name="maxValueBefore">映射前最大值</param>
        /// <param name="minValueAfter">映射后最小值</param>
        /// <param name="maxValueAfter">映射后最大值</param>
        public static float Remap(float value, float minValueBefore, float maxValueBefore, float minValueAfter, float maxValueAfter)
        {
            return (value - minValueBefore) / (maxValueBefore - minValueBefore) * (maxValueAfter - minValueAfter) + minValueAfter;
        }

        /// <summary>
        /// 取整
        /// </summary>
        /// <param name="value"></param>
        public static int ToInt(float value)
        {
            return (int)value;
        }
        /// <summary>
        /// 向上取整.
        /// 获取大于等于 <paramref name="value"/> 的最小整数
        /// </summary>
        public static float Ceil(float value)
        {
            int integer = (int)value;
            return integer == value ? integer : integer + 1f;
        }
        /// <summary>
        /// 向下取整.
        /// 获取小于等于 <paramref name="value"/> 的最大整数
        /// </summary>
        public static float Floor(float value)
        {
            return (float)System.Math.Floor(value);
        }
        /// <summary>
        /// 舍入.
        /// 仅考虑小数点后一位
        /// </summary>
        public static int Round(float value)
        {
            return (int)(value + 0.5f);//仅考虑小数点后1位
        }
        /// <summary>
        /// 舍入
        /// </summary>
        /// <param name="place">要舍入的位数</param>
        /// <param name="round">是否四舍五入</param>
        public static float Round(float value, int place, bool round = true)
        {
            if (round) return (float)System.Math.Round(value, place, MidpointRounding.AwayFromZero);//如果四舍五入, 直接返回
            float divisor = Pow(10f, place);
            return (int)(value * divisor) / divisor;
        }
        /// <summary>
        /// 取符号
        /// </summary>
        /// <param name="value"></param>
        public static float Sign(float value)
        {
            return value < 0f ? -1f : 1f;
        }
        /// <summary>
        /// 取符号.
        /// 如果 <paramref name="value"/> 为 true 返回 1; 否则返回 -1
        /// </summary>
        public static float Sign(bool value)
        {
            return value ? 1f : -1f;
        }
        /// <summary>
        /// 取符号.
        /// 如果 <paramref name="value"/> 为 0, 返回 0
        /// </summary>
        public static float SignZero(float value)
        {
            if (value == 0f) return 0f;
            return value < 0f ? -1f : 1f;
        }
        /// <summary>
        /// 近似
        /// </summary>
        public static bool Approximate(float a, float b)
        {
            return Mathf.Abs(a - b) < 0.000001f;
        }

        /// <summary>
        /// 绝对值
        /// </summary>
        public static int Abs(int value)
        {
            return Mathf.Abs(value);
        }
        /// <summary>
        /// 绝对值
        /// </summary>
        public static float Abs(float value)
        {
            return Mathf.Abs(value);
        }

        /// <summary>
        /// 平均值
        /// </summary>
        public static float Average(float value1, float value2)
        {
            return (value1 + value2) * 0.5f;
        }
        /// <summary>
        /// 平均值
        /// </summary>
        public static float Average(float value1, float value2, float value3)
        {
            return (value1 + value2 + value3) / 3f;
        }
        /// <summary>
        /// 平均值
        /// </summary>
        public static float Average(float value1, float value2, float value3, float value4)
        {
            return (value1 + value2 + value3 + value4) / 4f;
        }

        /// <summary>
        /// 最大值
        /// </summary>
        public static int Max(params int[] values)
        {
            int length = values.Length;
            if (length == 0) return default;
            int max = values[0];
            for (int i = 1; i < length; i++)
            {
                if (values[i] < max) continue;
                max = values[i];
            }
            return max;
        }
        /// <summary>
        /// 最大值
        /// </summary>
        public static int Max(int value1, int value2)
        {
            return value1 < value2 ? value2 : value1;
        }
        /// <summary>
        /// 最大值
        /// </summary>
        public static float Max(params float[] values)
        {
            int length = values.Length;
            if (length == 0) return default;
            float max = values[0];
            for (int i = 1; i < length; i++)
            {
                if (values[i] < max) continue;
                max = values[i];
            }
            return max;
        }
        /// <summary>
        /// 最大值
        /// </summary>
        public static float Max(float value1, float value2)
        {
            return value1 < value2 ? value2 : value1;
        }

        /// <summary>
        /// 最小值
        /// </summary>
        public static int Min(params int[] values)
        {
            int length = values.Length;
            if (length == 0) return default;
            int min = values[0];
            for (int i = 1; i < length; i++)
            {
                if (values[i] > min) continue;
                min = values[i];
            }
            return min;
        }
        /// <summary>
        /// 最小值
        /// </summary>
        public static int Min(int value1, int value2)
        {
            return value1 < value2 ? value1 : value2;
        }
        /// <summary>
        /// 最小值
        /// </summary>
        public static float Min(params float[] values)
        {
            int length = values.Length;
            if (length == 0) return default;
            float min = values[0];
            for (int i = 1; i < length; i++)
            {
                if (values[i] > min) continue;
                min = values[i];
            }
            return min;
        }
        /// <summary>
        /// 最小值
        /// </summary>
        public static float Min(float value1, float value2)
        {
            return value1 < value2 ? value1 : value2;
        }

        /// <summary>
        /// 最小最大值
        /// </summary>
        public static void MinMax(float value1, float value2, out float min, out float max)
        {
            min = max = value1;

            if (value2 < min) min = value2;
            else if (value2 > max) max = value2;
        }
        /// <summary>
        /// 最小最大值
        /// </summary>
        public static void MinMax(float value1, float value2, float value3, out float min, out float max)
        {
            min = max = value1;

            if (value2 < min) min = value2;
            else if (value2 > max) max = value2;

            if (value3 < min) min = value3;
            else if (value3 > max) max = value3;
        }
        /// <summary>
        /// 最小最大值
        /// </summary>
        public static void MinMax(float value1, float value2, float value3, float value4, out float min, out float max)
        {
            min = max = value1;

            if (value2 < min) min = value2;
            else if (value2 > max) max = value2;

            if (value3 < min) min = value3;
            else if (value3 > max) max = value3;

            if (value4 < min) min = value4;
            else if (value4 > max) max = value4;
        }
        /// <summary>
        /// 最小最大值
        /// </summary>
        public static void MinMax(float[] values, out float min, out float max)
        {
            if (values == null || values.Length == 0)
            {
                min = max = default;
                return;
            }
            min = max = values[0];
            for (int i = 1; i < values.Length; i++)
            {
                float value = values[i];
                if (value < min) min = value;
                else if (value > max) max = value;
            }
        }

        /// <summary>
        /// 重复.
        /// 求 <paramref name="value"/> 对 <paramref name="length"/> 的余数
        /// </summary>
        public static float Repeat(float value, float length)
        {
            return value - Floor(value / length) * length;
        }
        /// <summary>
        /// 靠近.
        /// 将值 <paramref name="current"/> 推进 <paramref name="delta"/> 直到 <paramref name="target"/>
        /// </summary>
        /// <param name="current">当前值</param>
        /// <param name="target">目标值</param>
        /// <param name="delta">每次靠近的值. 这个值应该与 <see cref="Time.deltaTime"/> 相关</param>
        public static float MoveTowards(float current, float target, float delta)
        {
            float distance = target - current;
            return Abs(distance) <= delta ? target : current + Sign(distance) * delta;
        }
        /// <summary>
        /// 靠近.
        /// 将值 <paramref name="current"/> 推进 <paramref name="delta"/> 直到 <paramref name="target"/>
        /// </summary>
        /// <param name="current">当前值</param>
        /// <param name="target">目标值</param>
        /// <param name="delta">每次靠近的值. 这个值应该与 <see cref="Time.deltaTime"/> 相关</param>
        /// <returns>如果 <paramref name="current"/> 等于 <paramref name="target"/> 返回 true</returns>
        public static bool MoveTowards(ref float current, float target, float delta)
        {
            float distance = target - current;
            if (Abs(distance) <= delta)
            {
                current = target;
                return true;
            }
            else
            {
                current += Sign(distance) * delta;
                return false;
            }
        }

        /// <summary>
        /// Sin.
        /// 通过弧度计算
        /// </summary>
        public static float Sin(float value)
        {
            return Mathf.Sin(value);
        }
        /// <summary>
        /// Cos.
        /// 通过弧度计算
        /// </summary>
        public static float Cos(float value)
        {
            return Mathf.Cos(value);
        }
        /// <summary>
        /// Cot.
        /// 通过弧度计算
        /// </summary>
        public static float Cot(float value)
        {
            return 1 / Mathf.Tan(value);
        }
        /// <summary>
        /// Tan.
        /// 通过弧度计算
        /// </summary>
        public static float Tan(float value)
        {
            return Mathf.Tan(value);
        }

        /// <summary>
        /// Sin.
        /// 通过角度计算
        /// </summary>
        public static float SinDeg(float value)
        {
            return Mathf.Sin(value * deg2Rad);
        }
        /// <summary>
        /// Cos.
        /// 通过角度计算
        /// </summary>
        public static float CosDeg(float value)
        {
            return Mathf.Cos(value * deg2Rad);
        }
        /// <summary>
        /// Cot.
        /// 通过角度计算
        /// </summary>
        public static float CotDeg(float value)
        {
            return 1 / Mathf.Tan(value * deg2Rad);
        }
        /// <summary>
        /// Tan.
        /// 通过角度计算
        /// </summary>
        public static float TanDeg(float value)
        {
            return Mathf.Tan(value * deg2Rad);
        }

        /// <summary>
        /// 反sin
        /// </summary>
        public static float Asin(float value)
        {
            if (!InRange(value, -1f, 1f)) throw new Exception($"{nameof(Math)}.{nameof(Acos)}: sin值应该在区间 [-1, 1] 内, 当前值为 {value}");
            return Mathf.Asin(value);
        }
        /// <summary>
        /// 反cos
        /// </summary>
        public static float Acos(float value)
        {
            if (!InRange(value, -1f, 1f)) throw new Exception($"{nameof(Math)}.{nameof(Acos)}: cos值应该在区间 [-1, 1] 内,当前值为 {value}");
            return Mathf.Acos(value);
        }

        /// <summary>
        /// 将点 <paramref name="position"/> 按照方向 <paramref name="projectionDirection"/> 投影到以平面点 <paramref name="planeOrigin"/> 和平面法线 <paramref name="planeNormal"/> 定义的平面中
        /// </summary>
        /// <param name="projectionPosition">如果返回值为 true, 表示投影点</param>
        public static bool ProjectToPlane(Vector3 position, Vector3 planeOrigin, Vector3 planeNormal, Vector3 projectionDirection, out Vector3 projectionPosition)
        {
            planeNormal.Normalize();
            projectionDirection.Normalize();
            float dot = Vector3.Dot(planeNormal, projectionDirection);
            if (Mathf.Approximately(dot, 0f))//如果点积为0, 说明夹角等于90度, 不可能有投影点
            {
                projectionPosition = Vector3.zero;
                return false;
            }
            float difference = Vector3.Dot(planeOrigin, planeNormal) - Vector3.Dot(position, planeNormal);
            float length = difference / dot;
            projectionPosition = position + projectionDirection * length;
            return true;
        }

        /// <summary>
        /// 点 <paramref name="position"/> 是否在三角形内.
        /// 三角形位于xz平面, <paramref name="height"/> 为y轴
        /// </summary>
        /// <param name="transform">Unity Transform 组件</param>
        /// <param name="position">判断点</param>
        /// <param name="angle">三角形角度</param>
        /// <param name="length">三角形长度</param>
        public static bool IsInTriangle(Transform transform, Vector3 position, float angle, float length)
        {
            Matrix4x4 worldToLocalMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one).inverse;
            Vector3 localPoint = worldToLocalMatrix.MultiplyPoint(position);
            if (localPoint.z > length) return false;
            localPoint.y = 0;
            if (Vector3.Angle(localPoint.normalized, Vector3.forward) > angle * 0.5f) return false;
            return true;
        }
        /// <summary>
        /// 点 <paramref name="position"/> 是否在三角形内.
        /// 三角形位于xz平面, <paramref name="height"/> 为y轴
        /// </summary>
        /// <param name="transform">Unity Transform 组件</param>
        /// <param name="position">判断点</param>
        /// <param name="angle">三角形角度</param>
        /// <param name="length">三角形长度</param>
        /// <param name="height">三角形的高度</param>
        /// <returns></returns>
        public static bool IsInTriangle(Transform transform, Vector3 position, float angle, float length, float height)
        {
            Matrix4x4 worldToLocalMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one).inverse;
            Vector3 localPoint = worldToLocalMatrix.MultiplyPoint(position);
            if (Abs(localPoint.y) > height * 0.5f) return false;
            if (localPoint.z > length) return false;
            localPoint.y = 0;
            if (Vector3.Angle(localPoint.normalized, Vector3.forward) > angle * 0.5f) return false;
            return true;
        }

        /// <summary>
        /// 点 <paramref name="position"/> 是否在扇形内.
        /// 该扇形位于xz平面
        /// </summary>
        /// <param name="transform">Unity Transform 组件</param>
        /// <param name="position">判断点</param>
        /// <param name="angle">扇形的角度</param>
        /// <param name="sideLength">扇形的边长</param>
        /// <param name="height">扇形的高度</param>
        /// <returns></returns>
        public static bool IsInSector(Transform transform, Vector3 position, float angle, float sideLength)
        {
            Matrix4x4 worldToLocalMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one).inverse;
            Vector3 localPosition = worldToLocalMatrix.MultiplyPoint(position);
            if (localPosition.sqrMagnitude > sideLength * sideLength) return false;
            localPosition.y = 0;
            if (Vector3.Angle(localPosition.normalized, Vector3.forward) > angle * 0.5f) return false;
            return true;
        }
        /// <summary>
        /// 点 <paramref name="position"/> 是否在扇形内.
        /// 该扇形位于xz平面, <paramref name="height"/> 为y轴
        /// </summary>
        /// <param name="transform">Unity Transform 组件</param>
        /// <param name="position">判断点</param>
        /// <param name="angle">扇形的角度</param>
        /// <param name="sideLength">扇形的边长</param>
        /// <param name="height">扇形的高度</param>
        /// <returns></returns>
        public static bool IsInSector(Transform transform, Vector3 position, float angle, float sideLength, float height)
        {
            Matrix4x4 worldToLocalMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one).inverse;
            Vector3 localPosition = worldToLocalMatrix.MultiplyPoint(position);
            if (Abs(localPosition.y) > height * 0.5f) return false;
            if (localPosition.sqrMagnitude > sideLength * sideLength) return false;
            localPosition.y = 0;
            if (Vector3.Angle(localPosition.normalized, Vector3.forward) > angle * 0.5f) return false;
            return true;
        }

        /// <summary>
        /// 点 <paramref name="position"/> 是否在球锥内
        /// </summary>
        /// <param name="transform"></param>
        /// <param name="position">判断点</param>
        /// <param name="angle">球锥的角度</param>
        /// <param name="sideLength">球锥的边长</param>
        /// <returns></returns>
        public static bool IsInBallCone(Transform transform, Vector3 position, float angle, float sideLength)
        {
            Matrix4x4 worldToLocalMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one).inverse;
            Vector3 localPosition = worldToLocalMatrix.MultiplyPoint(position);
            if (localPosition.sqrMagnitude > sideLength * sideLength) return false;
            if (Vector3.Angle(localPosition.normalized, Vector3.forward) > angle * 0.5f) return false;
            return true;
        }
        /// <summary>
        /// 点 <paramref name="position"/> 是否在圆锥内
        /// </summary>
        /// <param name="transform"></param>
        /// <param name="position">判断点</param>
        /// <param name="angle">圆锥的角度</param>
        /// <param name="length">圆锥的长度</param>
        /// <returns></returns>
        public static bool IsInCircularCone(Transform transform, Vector3 position, float angle, float length)
        {
            Matrix4x4 worldToLocalMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one).inverse;
            Vector3 localPosition = worldToLocalMatrix.MultiplyPoint(position);
            if (localPosition.z > length) return false;
            if (Vector3.Angle(localPosition.normalized, Vector3.forward) > angle * 0.5f) return false;
            return true;
        }

        /// <summary>
        /// 判断点 <paramref name="position"/> 是否位于相机 <paramref name="camera"/> 视锥体内
        /// </summary>
        public static bool IsInViewFrustum(Camera camera, Vector3 position)
        {
            Transform transform = camera.transform;
            Matrix4x4 worldToLocalMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one).inverse;
            Vector3 localposition = worldToLocalMatrix.MultiplyPoint3x4(position);
            float nearDistance = camera.nearClipPlane;
            float farDistance = camera.farClipPlane;
            float z = localposition.z;
            if (z < nearDistance || z > farDistance) return false;
            float scale = (z - nearDistance) / (farDistance - nearDistance);
            float tan = Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad);
            float nearHeight = nearDistance * tan;
            float farHeight = farDistance * tan;
            float halfHeight = (farHeight - nearHeight) * scale;
            float y = localposition.y;
            if (y < -halfHeight || y > halfHeight) return false;
            float aspect = camera.aspect;
            float halfWidth = halfHeight * aspect;
            float x = localposition.x;
            if (x < -halfWidth || x > halfWidth) return false;
            return true;
        }
        /// <summary>
        /// 判断值 <paramref name="value"/> 是否在区间 [<paramref name="minValue"/>, <paramref name="maxValue"/>] 内
        /// </summary>
        public static bool InRange(float value, float minValue, float maxValue)
        {
            return value <= maxValue && value >= minValue;
        }

        /// <summary>
        /// 是否为素数
        /// </summary>
        public static bool IsPrime(int number)
        {
            //质数(素数)是指大于1并且只能被1和自身整除的自然数
            if (number < 2) return false;//如果小于等于1，不是质数
            int sqrt = (int)Sqrt(number);//获取该数的平方根，这是因为除法中总有一个除数∈[1, 平方根]的范围内
            for (int i = 2; i <= sqrt; i++) if (number % i == 0) return false;//遍历从2到该数的平方根。如果余数为0，说明能整除，不是质数
            return true;//循环结束后还是不能整除，说明是质数
        }
        /// <summary>
        /// 是否为偶数
        /// </summary>
        public static bool IsEven(int number)
        {
            return (number & 1) == 0;// 任何偶数的二进制第一位都是0，所以只要是偶数，和1做 逻辑与 处理后，得到的总是0
        }
    }
}